package com.flow.framework.persistence.handler;

import com.flow.framework.cipher.algorithm.CipherUtil;
import com.flow.framework.cipher.algorithm.version.Sm4Version;
import com.flow.framework.common.error.SystemErrorCode;
import com.flow.framework.common.exception.CheckedException;
import com.flow.framework.common.util.verify.VerifyUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * 数据库字段加解密
 *
 * @author luoguopiao
 * @version 0.0.1
 * @date 2022/4/4
 */
@Slf4j
public class CustomizationSecurityHandler extends BaseTypeHandler<Object> {

    private static String secret;

    public CustomizationSecurityHandler() {
        VerifyUtil.requireNotEmpty(secret, () -> {
            log.error("secret is empty.");
            return new CheckedException(SystemErrorCode.SYSTEM_NOT_SUPPORT_ERROR);
        });
    }

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {
        if (null == parameter) {
            ps.setString(i, null);
            return;
        }
        ps.setString(i, CipherUtil.encryptBySm4(Sm4Version.SV1, String.valueOf(parameter), secret));
    }

    /**
     * @param rs
     * @param columnName Colunm name, when configuration <code>useColumnLabel</code> is <code>false</code>
     */
    @Override
    public Object getNullableResult(ResultSet rs, String columnName) throws SQLException {
        String value = rs.getString(columnName);
        if (VerifyUtil.isEmpty(value)) {
            return value;
        }
        return CipherUtil.decryptBySm4(Sm4Version.SV1, value, secret);
    }

    @Override
    public Object getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        String value = rs.getString(columnIndex);
        if (VerifyUtil.isEmpty(value)) {
            return value;
        }
        return CipherUtil.decryptBySm4(Sm4Version.SV1, value, secret);
    }

    @Override
    public Object getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        String value = cs.getString(columnIndex);
        if (VerifyUtil.isEmpty(value)) {
            return value;
        }
        return CipherUtil.decryptBySm4(Sm4Version.SV1, value, secret);
    }
}
